package info.motteke.mybws.xml;

import static org.apache.commons.lang3.StringUtils.*;
import info.motteke.mybws.Node;
import info.motteke.mybws.node.CellNode;
import info.motteke.mybws.node.ExcelNode;
import info.motteke.mybws.node.IterationNode;
import info.motteke.mybws.node.SheetNode;
import info.motteke.mybws.node.TextNode;

import java.util.LinkedList;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class NodeHandler extends DefaultHandler {

    private ExcelNode root;

    private Node currentNode;

    private LinkedList<String> currentTagNames = new LinkedList<String>();

    public ExcelNode getRoot() {
        return root;
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if (qName.equals("excel")) {
            currentNode = root = new ExcelNode();
        }

        if (qName.equals("sheet")) {
            newNode(new SheetNode(attributes.getValue("name")));
        }

        if (qName.equals("cell")) {
            newNode(new CellNode(attributes.getValue("position")));
        }

        if (qName.equals("iterate")) {
            newNode(new IterationNode(attributes.getValue("list")));
        }

        currentTagNames.push(qName);
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if (currentNode != null) {
            String text = new String(ch, start, length);

            if (isNotBlank(text)) {
                currentNode.addChild(new TextNode(text));
            }
        }
    }

    private void newNode(Node child) {
        currentNode.addChild(child);
        currentNode = child;
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        String tagName = currentTagNames.pop();

        if (!tagName.equals(qName)) {
            throw new SAXException("unclosed tag detected : " + tagName);
        }

        currentNode = currentNode.getParent();
    }
}
